package com.briup.pts.aop;

import com.briup.pts.config.auth.UserDetails;
import com.briup.pts.domain.bean.Account;
import com.briup.pts.domain.bean.Log;
import com.briup.pts.mapper.LogMapper;
import com.briup.pts.util.AssertUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.time.LocalDateTime;

/**
 * 日志记录的切面类
 */
@Aspect
@Component
@RequiredArgsConstructor
public class LoggerAspect {

    private final LogMapper mapper;

    // 设置切入点
    @Pointcut("execution(* com.briup.pts.web.controller..*(..)) && " +
            "@annotation(com.briup.pts.aop.Logger)")
    public void pointcut() {
    }

    // 使用环绕通知进行日志记录
    @Before("pointcut()")
    public void around() {
        // 获取当前请求的用户对象
        Account user = UserDetails.currentUser();
        Log sysLog = new Log();
        sysLog.setLogUsername(user.getUsername());
        sysLog.setLogRealname(user.getRealname());

        // 获取请求对象，解析请求数据
        parseRequest(sysLog);
        sysLog.setLogTime(LocalDateTime.now());

        // 将日志对象存入到数据库中
        mapper.addLog(sysLog);
    }

    private void parseRequest(Log sysLog) {
        // 从请求的上下文中获取请求对象
        ServletRequestAttributes requestAttributes
                = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
        AssertUtil.requiredNotNull(requestAttributes, "请求对象为null");
        HttpServletRequest request = requestAttributes.getRequest();

        // 获取请求中的数据
        String method = request.getMethod();
        sysLog.setLogRequestMethod(method);
        String uri = request.getRequestURI();
        sysLog.setLogRequestUri(uri);
        // 从请求中解析ip地址
        String ip = getIpAddress(request);
        sysLog.setLogHost(ip);
    }

    private String getIpAddress(HttpServletRequest request) {
        String sourceIp = null;
        String ipAddresses = request.getHeader("x-forwarded-for");
        if (ipAddresses == null || ipAddresses.isEmpty() || "unknown".equalsIgnoreCase(ipAddresses)) {
            ipAddresses = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddresses == null || ipAddresses.isEmpty() || "unknown".equalsIgnoreCase(ipAddresses)) {
            ipAddresses = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddresses == null || ipAddresses.isEmpty() || "unknown".equalsIgnoreCase(ipAddresses)) {
            ipAddresses = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ipAddresses == null || ipAddresses.isEmpty() || "unknown".equalsIgnoreCase(ipAddresses)) {
            ipAddresses = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ipAddresses == null || ipAddresses.isEmpty() || "unknown".equalsIgnoreCase(ipAddresses)) {
            ipAddresses = request.getRemoteAddr();
        }
        if (StringUtils.hasText(ipAddresses)) {
            sourceIp = ipAddresses.split(",")[0];
        }

        return sourceIp;
    }
}
